﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Data;

using Gurucore.Framework.Core;
using Gurucore.Framework.DataAccess.Persistence.QueryLanguage;

namespace Gurucore.Framework.DataAccess.Persistence
{
	public class FinalizedQuery<T> : Query<T> where T : class
	{
		private T m_sample;
		private string m_sQueryTarget;

		internal FinalizedQuery(T p_sample, string p_sQueryTarget, Expression p_expFilter, Order p_order, int p_nOffset, int p_nCount)
		{
			m_sample = p_sample;
			m_sQueryTarget = p_sQueryTarget;
			m_expFilter = p_expFilter;
			m_order = p_order;
		}

		public override FinalizedQuery<U> Into<U>(U p_sample) 
		{
			throw new Exception();
		}

		public override Query<T> Where(Expression p_exp)
		{
			throw new Exception();
		}

		public override Query<T> OrderBy(Expression p_exp, OrderType p_type)
		{
			throw new Exception();
		}

		public override Query<T> Limit(int p_nOffset, int p_nCount)
		{
			throw new Exception();
		}

		public override JoinQuery<T, U> Join<U>(Query<U> p_other, Expression p_exp)
		{
			throw new Exception();
		}

		public override JoinQuery<T, U> LeftJoin<U>(Query<U> p_other, Expression p_exp)
		{
			throw new Exception();
		}

		internal override string GetQueryTarget()
		{
			return m_sQueryTarget;
		}

		internal override List<string> GetColumnsList()
		{
			Type resultType = typeof(T);
			ComplexTypeInfoManager oComplexTypeInfoMgr = Application.GetInstance().GetGlobalSharedObject<ComplexTypeInfoManager>();
			TableInfoManager oTableInfoMgr = Application.GetInstance().GetGlobalSharedObject<TableInfoManager>();

			if (oComplexTypeInfoMgr.IsComplexType(resultType))
			{
				List<string> columns = new List<string>();
				ComplexTypeInfo complexTypeInfo = oComplexTypeInfoMgr.GetComplexTypeInfo(resultType);
				foreach (PropertyInfo prop in complexTypeInfo.Elements)
				{
					TableInfo tableInfo = oTableInfoMgr.GetTableInfo(prop.PropertyType);
					columns.AddRange(tableInfo.Column);
				}
				return columns;
			}
			else
			{
				TableInfo oTableInfo = oTableInfoMgr.GetTableInfo(typeof(T));
				return oTableInfo.Column;
			}
		}

		internal override T GetSample()
		{
			return m_sample;
		}

		internal override DTOTransformer GetBatchTransformer()
		{
			Type resultType = typeof(T);
			DataAccessConfiguration oDACfg = Application.GetInstance().GetGlobalSharedObject<DataAccessConfiguration>();
			string sTransformStrategy = oDACfg.TransformStrategy;
			switch (sTransformStrategy)
			{
				case "JIT":
					TransformerClassGenerator oGenerator = new TransformerClassGenerator(resultType);
					return oGenerator.GetTransformer();
				default:
					ComplexTypeInfoManager oComplexTypeInfoMgr = Application.GetInstance().GetGlobalSharedObject<ComplexTypeInfoManager>();
					if (oComplexTypeInfoMgr.IsComplexType(resultType))
					{
						return new ComplexDTOTransformer();
					}
					else
					{
						return new SingleDTOTransformer();
					}
			}
		}
	}
}
